{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 多层感知机的从零实现",
   "id": "353fc6617b78707"
  },
  {
   "cell_type": "code",
   "id": "initial_id",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-08-12T08:07:36.827758Z",
     "start_time": "2025-08-12T08:07:36.824864Z"
    }
   },
   "source": [
    "import torch\n",
    "from torch import nn\n",
    "from d2l import torch as d2l\n",
    "from utils_09 import load_data_fashion_mnist\n",
    "from utils_09 import Accumulator\n",
    "from utils_09 import evaluate_accuracy\n",
    "from utils_09 import accuracy\n"
   ],
   "outputs": [],
   "execution_count": 7
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-12T03:17:51.535345Z",
     "start_time": "2025-08-12T03:17:51.495130Z"
    }
   },
   "cell_type": "code",
   "source": [
    "batch_size = 512\n",
    "train_iter,test_iter =  load_data_fashion_mnist(batch_size,cpu_workers=5)"
   ],
   "id": "72bedb130710a110",
   "outputs": [],
   "execution_count": 52
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-12T03:17:51.556050Z",
     "start_time": "2025-08-12T03:17:51.550665Z"
    }
   },
   "cell_type": "code",
   "source": [
    "num_inputs = 784\n",
    "num_outputs = 10\n",
    "num_hidden_units = 256\n",
    "W1 = nn.Parameter(\n",
    "    torch.randn(num_inputs,num_hidden_units,requires_grad=True) * 0.01 ## 和torch.normal(0,0.01,(num_inputs,num_hidden_units),requires_grad = True)等价\n",
    ")\n",
    "b1 = nn.Parameter(\n",
    "    torch.zeros(num_hidden_units,requires_grad=True)\n",
    ")\n",
    "W2 = nn.Parameter(\n",
    "    torch.randn(num_hidden_units,num_outputs,requires_grad=True)\n",
    ")\n",
    "b2 = nn.Parameter(\n",
    "    torch.zeros(num_outputs,requires_grad=True)\n",
    ")\n",
    "params = [W1,b1,W2,b2]"
   ],
   "id": "41353d8dac0888ff",
   "outputs": [],
   "execution_count": 53
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-12T03:17:51.579426Z",
     "start_time": "2025-08-12T03:17:51.575954Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def relu(X:torch.utils.data.DataLoader[any]):\n",
    "    zero_mat = torch.zeros_like(X)\n",
    "    activate_weight = torch.max(X,zero_mat)\n",
    "    return activate_weight"
   ],
   "id": "f03137ed0a6f3b8e",
   "outputs": [],
   "execution_count": 54
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-12T03:17:51.602044Z",
     "start_time": "2025-08-12T03:17:51.598772Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def net(X:torch.utils.data.DataLoader[any]):\n",
    "    X = X.reshape((-1,num_inputs))\n",
    "    H = relu(torch.matmul(X,W1) + b1)\n",
    "    return (H @ W2 + b2) ## @ 和 torch.matmul等价，都是矩阵乘法"
   ],
   "id": "92d89c6c4be78ba2",
   "outputs": [],
   "execution_count": 55
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-12T03:17:51.627627Z",
     "start_time": "2025-08-12T03:17:51.624391Z"
    }
   },
   "cell_type": "code",
   "source": "loss = nn.CrossEntropyLoss()",
   "id": "19cc09bde7d7cbbd",
   "outputs": [],
   "execution_count": 56
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-12T03:22:18.078029Z",
     "start_time": "2025-08-12T03:17:51.671892Z"
    }
   },
   "cell_type": "code",
   "source": [
    "num_epochs = 30\n",
    "lr = 0.1\n",
    "updater = torch.optim.SGD(params,lr=lr)\n",
    "metric = Accumulator(3)\n",
    "train_loss_record = list()\n",
    "train_acc_record = list()\n",
    "test_acc_record = list()\n",
    "for epoch in range(num_epochs):\n",
    "    for X,y in train_iter:\n",
    "        y_predict = net(X)\n",
    "        l = loss(y_predict,y)\n",
    "        updater.zero_grad()\n",
    "        l.mean().backward()\n",
    "        updater.step()\n",
    "        metric.add(float(l.sum()),accuracy(y_predict,y),y.numel())\n",
    "    train_metric = (metric[0]/metric[2],metric[1]/metric[2])\n",
    "    test_acc = evaluate_accuracy(net,test_iter)\n",
    "    print(f\"epoch {epoch}, train loss : {train_metric[0]}, train acc : {train_metric[1]},test_acc : {test_acc}\")\n",
    "    train_loss_record.append(train_metric[0])\n",
    "    train_acc_record.append(train_metric[1])\n",
    "    test_acc_record.append(test_acc)\n",
    "train_loss, train_acc = train_metric ## 训练结束，输出训练指标"
   ],
   "id": "3564ec7991e8c5af",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch 0, train loss : 0.01388656977514426, train acc : 0.5918333333333333,test_acc : 0.7086333333333333\n",
      "epoch 1, train loss : 0.007618012035389741, train acc : 0.680875,test_acc : 0.77875\n",
      "epoch 2, train loss : 0.0054485707489980596, train acc : 0.7223666666666667,test_acc : 0.7984166666666667\n",
      "epoch 3, train loss : 0.0043367763849596185, train acc : 0.7466958333333333,test_acc : 0.7995666666666666\n",
      "epoch 4, train loss : 0.003656985270678997, train acc : 0.7635233333333333,test_acc : 0.8168333333333333\n",
      "epoch 5, train loss : 0.0031954410120017, train acc : 0.7760777777777778,test_acc : 0.8421666666666666\n",
      "epoch 6, train loss : 0.002860846220382622, train acc : 0.7858904761904761,test_acc : 0.8403\n",
      "epoch 7, train loss : 0.002604816530148188, train acc : 0.7940708333333333,test_acc : 0.8358666666666666\n",
      "epoch 8, train loss : 0.0024049200034803814, train acc : 0.8006314814814814,test_acc : 0.8385166666666667\n",
      "epoch 9, train loss : 0.00224247482513388, train acc : 0.806225,test_acc : 0.8520333333333333\n",
      "epoch 10, train loss : 0.0021085420704474956, train acc : 0.8109818181818181,test_acc : 0.8583833333333334\n",
      "epoch 11, train loss : 0.0019959357772229448, train acc : 0.8152416666666666,test_acc : 0.8337833333333333\n",
      "epoch 12, train loss : 0.001899203211393876, train acc : 0.8189653846153846,test_acc : 0.8500833333333333\n",
      "epoch 13, train loss : 0.0018155860024371318, train acc : 0.8223261904761905,test_acc : 0.8397833333333333\n",
      "epoch 14, train loss : 0.0017425952215823863, train acc : 0.8253877777777778,test_acc : 0.86245\n",
      "epoch 15, train loss : 0.0016775488438550382, train acc : 0.8282333333333334,test_acc : 0.8459833333333333\n",
      "epoch 16, train loss : 0.001619959980015661, train acc : 0.8307843137254902,test_acc : 0.8635333333333334\n",
      "epoch 17, train loss : 0.0015678952214342576, train acc : 0.8332240740740741,test_acc : 0.8673666666666666\n",
      "epoch 18, train loss : 0.0015216619975211329, train acc : 0.835278947368421,test_acc : 0.86325\n",
      "epoch 19, train loss : 0.001479177835037311, train acc : 0.8373633333333333,test_acc : 0.8435833333333334\n",
      "epoch 20, train loss : 0.001440350671396369, train acc : 0.8392547619047619,test_acc : 0.87675\n",
      "epoch 21, train loss : 0.0014046845991277333, train acc : 0.8410515151515151,test_acc : 0.8446166666666667\n",
      "epoch 22, train loss : 0.001372303373031858, train acc : 0.8426746376811595,test_acc : 0.8759166666666667\n",
      "epoch 23, train loss : 0.0013424909639896618, train acc : 0.8442138888888889,test_acc : 0.8381833333333333\n",
      "epoch 24, train loss : 0.001314725877225399, train acc : 0.8456333333333333,test_acc : 0.8654333333333334\n",
      "epoch 25, train loss : 0.0012888787831346958, train acc : 0.8470134615384616,test_acc : 0.8282666666666667\n",
      "epoch 26, train loss : 0.0012644778772728678, train acc : 0.8483771604938272,test_acc : 0.86835\n",
      "epoch 27, train loss : 0.0012416232123438802, train acc : 0.8496619047619047,test_acc : 0.8382\n",
      "epoch 28, train loss : 0.0012205066814676099, train acc : 0.8508844827586207,test_acc : 0.85265\n",
      "epoch 29, train loss : 0.0012005814535419146, train acc : 0.8520211111111111,test_acc : 0.8777333333333334\n"
     ]
    }
   ],
   "execution_count": 58
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
